#pragma once
#include <functional>
#include <string>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/types.h>
class tcp_reactor_t;

// 将epoll模型内的一个单位(rbtree内的一个节点? )进行封装:fd+关心事件+事件处理方法+读写缓冲区
struct connection_t
{
    using handler_t = std::function<bool(connection_t &)>;

public:
    tcp_reactor_t *get_server() const
    {
        return _p_server;
    }
    int get_fd() const
    {
        return _event.data.fd;
    }
    epoll_event *get_event()
    {
        return &_event;
    }
    uint32_t get_events() const
    {
        return _event.events;
    }

public:
    // 每个fd都有自己的缓冲区
    std::string _in_buffer;
    std::string _out_buffer;
    // 要发送的文件 sendfile
    int _sendfile_fd = -1;
    ssize_t _file_size = 0;

private:
    // epoll event ->data,events
    epoll_event _event;
    // 每个fd都有自己处理读写异常的方法
    handler_t _recv_handler;
    handler_t _send_handler;
    handler_t _error_handler;
    // 回指自己的服务器 便于释放资源
    tcp_reactor_t *_p_server;

public:
    // 初始化fd和关心事件
    connection_t(int fd, tcp_reactor_t *p_server, const u_int32_t care = 0, const handler_t &recv_func = handler_t(), const handler_t &send_func = handler_t(), const handler_t &error_func = handler_t())
        : _recv_handler(recv_func), _p_server(p_server), _send_handler(send_func), _error_handler(error_func)
    {
        _event.data.fd = fd;
        _event.events = EPOLLET | care;
    }
    ~connection_t()
    {
        if (_event.data.fd >= 0)
            close(_event.data.fd);
        if (_sendfile_fd >= 0)
            close(_sendfile_fd);
    }
    // 设置回调
    void set_recv_handler(const handler_t &recv_func)
    {
        _recv_handler = recv_func;
    }
    void set_send_handler(const handler_t &send_func)
    {
        _send_handler = send_func;
    }
    void set_error_handler(const handler_t &error_func)
    {
        _error_handler = error_func;
    }
    // 调用回调 为了防止非法调用引起的崩溃要提前判断调用是否合法
    bool is_func_exist_recv()
    {
        return _recv_handler.operator bool();
    }
    bool is_func_exist_send()
    {
        return _send_handler.operator bool();
    }
    bool is_func_exist_error()
    {
        return _error_handler.operator bool();
    }
    bool recv_handler()
    {
        if (is_func_exist_recv())
            return _recv_handler(*this);
        return false;
    };
    bool send_handler()
    {
        if (is_func_exist_send())
            return _send_handler(*this);
        return false;
    };
    bool error_handler()
    {
        if (is_func_exist_error())
            return _error_handler(*this);
        return false;
    };
};